import logging

from django.conf import settings
# Create your views here.
from django.db import transaction
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from demo.demo_access_mgmt.models import Role, Permission, RolePermissions, User, RoleUsers
from demo.demo_access_mgmt.serializers import RoleSerializer, PermissionSerializer, RolePermissionsSerializer, \
    UserSerializer, RoleUsersSerializer
from demo.demo_access_mgmt.view_helper.role_helper import RoleHelper
from demo.demo_access_mgmt.view_helper.user_helper import UserHelper
from demo_common_module.utils.cache_utils import CacheUtils
from demo_common_module.utils.exception_type import Exception400, Exception500, Exception200
from demo_common_module.utils.result_utils import ResultUtils

logger = logging.getLogger("info")


class RoleUserApiView(APIView):
    """角色用户管理"""
    role_id = openapi.Parameter("role_id", openapi.IN_QUERY, description="角色id",
                                type=openapi.TYPE_INTEGER, required=True)

    @swagger_auto_schema(
        operation_description="获取角色的权限",
        responses={200: "success"},
        manual_parameters=[role_id]
    )
    def get(self, request):
        role_id = request.query_params.get("role_id")
        role_user_objs = RoleUsers.objects.filter(role_id=role_id)
        user_ids = [role_user_obj.user_id for role_user_obj in role_user_objs]
        user_objs = User.objects.filter(user_id__in=user_ids)
        serializer = UserSerializer(user_objs, many=True)

        return Response({"status": "success", "message": "Query Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="增加角色的用户",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_id", "user_ids"],
            properties={
                "role_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="role_id"),
                "user_ids": openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    description="user_ids",
                    items=openapi.Items(type=openapi.TYPE_INTEGER),
                ),
            },
        ),
    )
    def post(self, request):
        """一个角色对应多个用户"""
        role_id = request.data.get("role_id")
        user_ids = request.data.get("user_ids")

        if not all([role_id]):
            raise Exception400("缺少参数")

        with transaction.atomic():
            # 把该角色下的所有用户都删除掉
            RoleUsers.objects.filter(role_id=role_id).delete()
            datas = [{"role_id": role_id, "user_id": user_id} for user_id in user_ids]
            serializer = RoleUsersSerializer(data=datas, many=True)
            serializer.is_valid(raise_exception=True)
            serializer.save()

        return Response({"status": "success", "message": "Create Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="删除角色的用户",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_id", "user_ids"],
            properties={
                "role_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="role_id"),
                "user_ids": openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    description="user_ids",
                    items=openapi.Items(type=openapi.TYPE_INTEGER),
                ),
            },
        ),
    )
    def delete(self, request):
        """移除角色的用户 一个角色对应多个用户"""
        role_id = request.data.get("role_id")
        user_ids = request.data.get("user_ids")

        if not all([role_id, user_ids]):
            raise Exception400("缺少参数")

        RoleUsers.objects.filter(role_id=role_id, user_id__in=user_ids).delete()
        return Response({"status": "success", "message": "Delete Success"},
                        status=status.HTTP_200_OK)


class RolePermissionApiView(APIView):
    """角色权限维护"""
    role_id = openapi.Parameter("role_id", openapi.IN_QUERY, description="角色id",
                                type=openapi.TYPE_INTEGER, required=True)

    @swagger_auto_schema(
        operation_description="获取角色的权限",
        responses={200: "success"},
        manual_parameters=[role_id]
    )
    def get(self, request):
        role_id = request.query_params.get("role_id")
        if not role_id:
            raise Exception400("缺少角色id")
        try:
            role_obj = Role.objects.get(id=role_id)
        except Exception:
            raise Exception200('该角色不存在')

        role_permission_objs = RolePermissions.objects.filter(role_id=role_id)
        permission_ids = [role_permission_obj.permission_id for role_permission_obj in role_permission_objs]
        # 查看该角色是否为admin
        if role_obj.name == settings.SYSTEM_SUPER_ROLE:
            role_permission_list = RoleHelper.get_role_permission(permission_ids, True)
        else:
            role_permission_list = RoleHelper.get_role_permission(permission_ids)

        return Response({"status": "success", "message": "Query Success", "data": role_permission_list},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="增加角色的权限",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_id", "permission_ids"],
            properties={
                "role_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="role_id"),
                "permission_ids": openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    description="permission_ids",
                    items=openapi.Items(type=openapi.TYPE_INTEGER),
                ),
            },
        ),
    )
    def post(self, request):
        role_id = request.data.get("role_id")
        permission_ids = request.data.get("permission_ids")

        if not all([role_id, permission_ids]):
            raise Exception400("缺少参数")

        with transaction.atomic():
            # 删除该角色的权限
            RolePermissions.objects.filter(role_id=role_id).delete()
            datas = [{"role_id": role_id, "permission_id": permission_id} for permission_id in permission_ids]
            serializer = RolePermissionsSerializer(data=datas, many=True)
            serializer.is_valid(raise_exception=True)
            serializer.save()

        return Response({"status": "success", "message": "Create Success", "data": serializer.data},
                        status=status.HTTP_200_OK)


class PermissionManagementApiView(APIView):
    """权限管理"""
    permission_id = openapi.Parameter("permission_id", openapi.IN_QUERY, description="权限id",
                                      type=openapi.TYPE_INTEGER, required=True)

    parent_id = openapi.Parameter("parent_id", openapi.IN_QUERY, description="父id",
                                  type=openapi.TYPE_INTEGER, required=False)

    page = openapi.Parameter("page", openapi.IN_QUERY, description="页码",
                             type=openapi.TYPE_INTEGER, required=False)

    n = openapi.Parameter("n", openapi.IN_QUERY, description="条数",
                          type=openapi.TYPE_INTEGER, required=False)

    @swagger_auto_schema(
        operation_description="获取权限信息",
        responses={200: "success"},
        manual_parameters=[parent_id, page, n]
    )
    def get(self, request):
        parent_id = request.query_params.get("parent_id", 0)
        page = int(request.query_params.get("page", 1))
        n = int(request.query_params.get("n", 10))

        permission_objs = Permission.objects.filter(parent_id=parent_id).order_by("weight")[(page - 1) * n: page * n]
        total = Permission.objects.filter(parent_id=parent_id).count()

        serializer = PermissionSerializer(permission_objs, many=True)
        ResultUtils.process_result(serializer.data)
        return Response({"status": "success", "message": "Query Success", "data": serializer.data, "total": total},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="增加权限信息",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["parent_id", "title", "url", "name", "weight", "type_name"],
            properties={
                "parent_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="parent_id"),
                "title": openapi.Schema(type=openapi.TYPE_STRING, description="标题"),
                "url": openapi.Schema(type=openapi.TYPE_STRING, description="url"),
                "name": openapi.Schema(type=openapi.TYPE_STRING, description="url的别名"),
                "icon": openapi.Schema(type=openapi.TYPE_STRING, description="图标"),
                "weight": openapi.Schema(type=openapi.TYPE_STRING, description="权重排序"),
                "type_name": openapi.Schema(type=openapi.TYPE_STRING, description="类型名称"),
            },
        ),
    )
    def post(self, request):
        title = request.data.get("title")
        url = request.data.get("url")
        name = request.data.get("name")

        if not all([title, url, name]):
            raise Exception400("参数不全")

        # permission_objs = Permission.objects.filter(title=title)
        # if permission_objs:
        #     raise Exception200("该标题已存在")

        serializer = PermissionSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({"status": "success", "message": "Create Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="修改权限信息",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["permission_id", "parent_id", "title", "url", "name", "type_name"],
            properties={
                "permission_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="权限id"),
                "parent_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="父id"),
                "title": openapi.Schema(type=openapi.TYPE_STRING, description="标题"),
                "url": openapi.Schema(type=openapi.TYPE_STRING, description="url"),
                "name": openapi.Schema(type=openapi.TYPE_STRING, description="url的别名"),
                "icon": openapi.Schema(type=openapi.TYPE_STRING, description="图标"),
                "weight": openapi.Schema(type=openapi.TYPE_STRING, description="权重排序"),
                "type_name": openapi.Schema(type=openapi.TYPE_STRING, description="类型名称"),
            },
        ),
    )
    def put(self, request):
        permission_id = request.data.get("permission_id")
        title = request.data.get("title")
        url = request.data.get("url")
        name = request.data.get("name")

        if not all([permission_id, title, url, name]):
            raise Exception400("缺少参数")

        # permission_objs = Permission.objects.filter(title=title)
        # if permission_objs:
        #     if permission_id != permission_objs[0].id:
        #         raise Exception200("该标题已存在")
        try:
            permission_obj = Permission.objects.get(id=permission_id)
        except Exception:
            raise Exception200('该权限不存在')

        serializer = PermissionSerializer(permission_obj, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({"status": "success", "message": "Update Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="删除权限",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["permission_id"],
            properties={
                "permission_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="角色id"),
            },
        ),
    )
    def delete(self, request):
        permission_id = request.data.get("permission_id")

        if not permission_id:
            raise Exception400("缺少permission_id")

        permission_objs = Permission.objects.filter(parent_id=permission_id)
        if permission_objs:
            raise Exception200("子节点非空")

        with transaction.atomic():
            # 删除权限表里的数据
            Permission.objects.filter(id=permission_id).delete()
            # 删除关联表 tb_role_permissions里的数据
            RolePermissions.objects.filter(permission_id=permission_id).delete()

        return Response({"status": "success", "message": "Delete Success"}, status=status.HTTP_200_OK)


class RoleManagementApiView(APIView):
    """角色管理"""
    role_id = openapi.Parameter("role_id", openapi.IN_QUERY, description="角色id",
                                type=openapi.TYPE_INTEGER, required=True)

    page = openapi.Parameter("page", openapi.IN_QUERY, description="页码",
                             type=openapi.TYPE_INTEGER, required=False)

    n = openapi.Parameter("n", openapi.IN_QUERY, description="条数",
                          type=openapi.TYPE_INTEGER, required=False)

    @swagger_auto_schema(
        operation_description="获取角色的信息",
        responses={200: "success"},
        manual_parameters=[page, n]
    )
    def get(self, request):
        page = int(request.query_params.get("page", 1))
        n = int(request.query_params.get("n", 100))
        roles = Role.objects.all().order_by("-create_time")[(page - 1) * n: page * n]
        total = Role.objects.all().count()
        serializer = RoleSerializer(roles, many=True)
        ResultUtils.process_result(serializer.data)
        return Response({"status": "success", "message": "Query Success", "data": serializer.data, "total": total},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="增加角色",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_name", "create_user"],
            properties={
                "role_name": openapi.Schema(type=openapi.TYPE_STRING, description="角色名"),
                "create_user": openapi.Schema(type=openapi.TYPE_STRING, description="创建人"),
            },
        ),
    )
    def post(self, request):
        role_name = request.data.get("role_name")
        create_user = request.data.get("create_user")

        if not all([role_name, create_user]):
            raise Exception400("缺少角色名或创建人")

        role_objs = Role.objects.filter(name=role_name)
        if role_objs:
            raise Exception200("该角色名已存在")

        data = {
            "name": role_name,
            "create_user": create_user
        }
        serializer = RoleSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response({"status": "success", "message": "Create Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="更新角色",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_id", "role_name", "create_user"],
            properties={
                "role_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="角色id"),
                "role_name": openapi.Schema(type=openapi.TYPE_STRING, description="角色名"),
                "create_user": openapi.Schema(type=openapi.TYPE_STRING, description="创建人"),
            },
        ),
    )
    def put(self, request):
        role_id = request.data.get("role_id")
        role_name = request.data.get("role_name")
        create_user = request.data.get("create_user")

        if not all([role_id, role_name, create_user]):
            raise Exception400("缺少角色id或角色名或创建人")

        try:
            role_obj = Role.objects.get(id=role_id)
        except Exception:
            raise Exception200('该角色不存在')

        if role_obj.name == settings.SYSTEM_SUPER_ROLE:
            raise Exception200("admin角色不允许修改")

        role_objs = Role.objects.filter(name=role_name)
        if role_objs:
            if role_id != role_objs[0].id:
                raise Exception200("该角色名已存在")

        try:
            role_obj = Role.objects.get(id=role_id)
        except Exception:
            raise Exception200('该角色不存在')

        data = {
            "name": role_name,
            "create_user": create_user
        }
        serializer = RoleSerializer(role_obj, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({"status": "success", "message": "Update Success", "data": serializer.data},
                        status=status.HTTP_200_OK)

    @swagger_auto_schema(
        operation_description="删除角色",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            required=["role_id"],
            properties={
                "role_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="角色id"),
            },
        ),
    )
    def delete(self, request):
        role_id = request.data.get("role_id")
        if not role_id:
            raise Exception400("缺少角色id")

        try:
            role_obj = Role.objects.get(id=role_id)
        except Exception:
            raise Exception200('该角色不存在')

        if role_obj.name == settings.SYSTEM_SUPER_ROLE:
            raise Exception200("admin角色不允许删除")

        role_user_objs = RoleUsers.objects.filter(role_id=role_id)
        if role_user_objs:
            raise Exception200("该角色下存在用户，不能删除")
        with transaction.atomic():
            # 删除角色表里的数据
            Role.objects.filter(id=role_id).delete()
            # 删除关联表角色权限表的数据
            RolePermissions.objects.filter(role_id=role_id).delete()
            # 删除关联表角色用户表的数据
            RoleUsers.objects.filter(role_id=role_id).delete()

        return Response({"status": "success", "message": "Delete Success"}, status=status.HTTP_200_OK)


class UserListApiView(APIView):
    """用户列表"""
    user_id = openapi.Parameter("user_id", openapi.IN_QUERY, description="用户名",
                                type=openapi.TYPE_STRING, required=False)

    user_name = openapi.Parameter("user_name", openapi.IN_QUERY, description="姓名",
                                  type=openapi.TYPE_STRING, required=False)

    # role_name = openapi.Parameter("role_name", openapi.IN_QUERY, description="角色名称",
    #                               type=openapi.TYPE_STRING, required=False)

    location = openapi.Parameter("location", openapi.IN_QUERY, description="基地名称",
                                 type=openapi.TYPE_STRING, required=False)

    department = openapi.Parameter("department", openapi.IN_QUERY, description="部门名称",
                                   type=openapi.TYPE_STRING, required=False)

    page = openapi.Parameter("page", openapi.IN_QUERY, description="页码",
                             type=openapi.TYPE_INTEGER, required=False)

    n = openapi.Parameter("n", openapi.IN_QUERY, description="条数",
                          type=openapi.TYPE_INTEGER, required=False)

    @swagger_auto_schema(
        operation_description="查询用户列表",
        responses={200: "success"},
        manual_parameters=[user_id, user_name, location, department, page, n]
    )
    def get(self, request):
        user_id = request.query_params.get("user_id")
        user_name = request.query_params.get("user_name")
        # role_name = request.query_params.get("role_name")
        location = request.query_params.get("location")
        department = request.query_params.get("department")
        page = int(request.query_params.get("page", 1))
        n = int(request.query_params.get("n", 10))

        query_condition = dict()
        if user_id:
            query_condition["user_id__icontains"] = user_id
        if user_name:
            query_condition["user_name__icontains"] = user_name
        if location:
            query_condition["location__icontains"] = location
        if department:
            query_condition["department__icontains"] = department

        if query_condition:
            total = User.objects.filter(**query_condition).count()
            user_objs = User.objects.filter(**query_condition).order_by("-create_time")[(page - 1) * n: page * n]
        else:
            total = User.objects.all().count()
            user_objs = User.objects.all().order_by("-create_time")[(page - 1) * n: page * n]

        serializer = UserSerializer(user_objs, many=True)

        # 给每条用户添加多个角色名
        RoleHelper.add_role_names_to_user_list(serializer.data)

        return Response({"status": "success", "message": "Query Success", "data": serializer.data, "total": total},
                        status=status.HTTP_200_OK)


class UserLogoutApiView(APIView):

    @swagger_auto_schema(
        operation_description="用户退出",
        responses={200: "success"},
    )
    def post(self, request):
        token = request.META.get("HTTP_AUTHORIZATION")
        if not token:
            raise Exception400("缺少token")
        # 清除redis里token
        CacheUtils().clear_user_info(token)
        return Response({"status": "success", "message": "Logout Success", }, status=status.HTTP_200_OK)


class UserInfoApiView(APIView):

    @swagger_auto_schema(
        operation_description="获取用户信息",
        responses={200: "success"},
    )
    def get(self, request):
        # 只需要请求头即可
        token = request.META.get("HTTP_AUTHORIZATION")
        if not token:
            raise Exception400("缺少token")

        # 通过token获取用户名
        try:
            user_id = UserHelper.get_sso_user_info(token)
            if not user_id:
                return Response({"status": "timeout", "message": "The token is invalid, please log in again"})
            user_obj = User.objects.filter(user_id=user_id)[0]
        except Exception as e:
            raise Exception500(repr(e))

        # 判断用户的状态是否启用
        if user_obj.status in ["514", "66050"]:
            raise Exception200("该用户未启用")

        role_names, permission_ids = RoleHelper.get_role_and_permission(user_id)
        permission_objs = Permission.objects.filter(id__in=permission_ids)

        permission_url_method_dict = {permission_obj.url: list() for permission_obj in permission_objs}
        for permission_obj in permission_objs:
            permission_url_methods = permission_url_method_dict.get(permission_obj.url)
            permission_url_methods.append(permission_obj.type_name)

        # 如果拥有admin角色，那么拥有所有权限
        if settings.SYSTEM_SUPER_ROLE in role_names:
            role_permission_list = RoleHelper.get_user_permission(permission_ids, is_admin=True)
        else:
            role_permission_list = RoleHelper.get_user_permission(permission_ids) if permission_ids else list()

        user_info = UserSerializer(user_obj).data

        # 把组合好的信息，存储到redis
        user_data = {
            "token": token,
            "user_info": user_info,
            "role_names": role_names,
            "permission_url_method_dict": permission_url_method_dict
        }
        # 把用户数据存储到缓存中
        CacheUtils().save_user_info(token, user_data)

        return Response(
            {"status": "success", "message": "Query Success", "token": token, "user_info": user_info,
             "roles": role_names, "permissions": role_permission_list}, status=status.HTTP_200_OK)
